package org.unicen.exa.io.worker.assigner.input;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.unicen.exa.io.worker.assigner.core.model.InstancesType;
import org.unicen.exa.io.worker.assigner.core.model.Job;
import org.unicen.exa.io.worker.assigner.core.model.JobWorking;
import org.unicen.exa.io.worker.assigner.core.model.ModelBuilder;
import org.unicen.exa.io.worker.assigner.core.model.Region;
import org.unicen.exa.io.worker.assigner.core.model.Worker;
import org.unicen.exa.io.worker.assigner.core.state.StatesConstants;
import org.unicen.exa.io.worker.assigner.dao.JobDao;
import org.unicen.exa.io.worker.assigner.dao.JobWorkingDao;
import org.unicen.exa.io.worker.assigner.dao.WorkerDao;

@Component
public class HandlerInstances implements Runnable {

	private Logger logger = Logger.getLogger(HandlerInstances.class);

	private @Autowired WorkerDao<Worker> workerDao;
	private @Autowired JobWorkingDao<JobWorking> jobWorkingDao;
	private @Autowired JobDao<Job> jobDao;
	private Integer timeInSecond;
	private boolean stop = false;

	public HandlerInstances() {
	}

	@Value("#{appProperties.timeInSecond}")
	public void setTimeInSecond(int timeInSecond) {
		this.timeInSecond = timeInSecond;
	}

	public void run() {

		ExecutorService executor = Executors.newSingleThreadScheduledExecutor();

		Long id = 1l;
		while (!stop) {
			try {
				Integer jobsInPending = jobDao.countJobsByState(StatesConstants.JOB_STATE_PENDING);
				Integer jobsInTranscoding = jobDao.countJobsByState(StatesConstants.JOB_STATE_TRANSCODING);
				Integer workerActives = workerDao.countWorkersByState(StatesConstants.WORKER_INSTANCES_WORKING);
				List<Worker> workers = new ArrayList<Worker>();

				logger.debug(String.format("CREATING a worker instances"));
				if ((jobsInPending > 0) && (workerActives == 0) && (jobsInTranscoding == 0)) {
					Worker worker = ModelBuilder.buildWorker(id++, InstancesType.SMALL, Region.US, 6.0f);
					workers.add(worker);
				} else {
					if (jobsInPending > 100) {
						Worker worker = ModelBuilder.buildWorker(id++, InstancesType.SMALL, Region.US, 6.0f);
						workers.add(worker);
					} 
//					else {
//						workers.add(ModelBuilder.buildWorker(id++, InstancesType.SMALL, Region.US, 6.0f));
//						workers.add(ModelBuilder.buildWorker(id++, InstancesType.SMALL, Region.US, 6.0f));
//					}
				}
				putWorkers(workers, executor);
				Thread.sleep(timeInSecond * 1000);
			} catch (InterruptedException e) {
				e.getStackTrace();
				stop=true;
				logger.error(e);
			}

		}
	}

	private void putWorkers(List<Worker> workers, ExecutorService executor) {
		for (Worker worker : workers) {
			WorkerInstance workerInstance = new WorkerInstance(worker, workerDao, jobWorkingDao, jobDao, timeInSecond);
			logger.debug(String.format("CREATING instances with id=%s", worker.getId()));
			executor.submit(workerInstance);
			logger.debug(String.format("SETTING instances with id=%s and state %s", worker.getId(), StatesConstants.WORKER_INSTANCES_BOOTING));
		}
	}

}
